#ifndef LIBZHI_H
#define LIBZHI_H

#ifndef LIBZHIAPI
# define LIBZHIAPI
#endif

#ifdef __cplusplus
extern "C" {
#endif

/*****************************/
/* set custom allocator for all allocations (optional) */

typedef void *ZHIReallocFunc(void *ptr, unsigned long size);
LIBZHIAPI void zhi_set_realloc(ZHIReallocFunc *my_realloc);

/*****************************/

typedef struct ZHIState ZHIState;

/* create a new ZHI compilation context */
LIBZHIAPI ZHIState *zhi_new(void);

/* free a ZHI compilation context */
LIBZHIAPI void zhi_delete(ZHIState *s);

/* set CONFIG_ZHIDIR at runtime */
LIBZHIAPI void zhi_set_lib_path(ZHIState *s, const char *path);

/* set error/warning callback (optional) */
typedef void ZHIErrorFunc(void *opaque, const char *msg);
LIBZHIAPI void zhi_set_error_func(ZHIState *s, void *error_opaque, ZHIErrorFunc *error_func);

/* set options as from command line (multiple supported) */
LIBZHIAPI int zhi_set_options(ZHIState *s, const char *str);

/*****************************/
/* preprocessor */

/* add include path */
LIBZHIAPI int zhi_add_include_path(ZHIState *s, const char *pathname);

/* add in system include path */
LIBZHIAPI int zhi_add_sysinclude_path(ZHIState *s, const char *pathname);

/* define preprocessor symbol 'sym'. value can be NULL, sym can be "sym=val" */
LIBZHIAPI void zhi_define_symbol(ZHIState *s, const char *sym, const char *value);

/* undefine preprocess symbol 'sym' */
LIBZHIAPI void zhi_undefine_symbol(ZHIState *s, const char *sym);

/*****************************/
/* compiling */

/* add a file (C file, dll, object, library, ld script). Return -1 if error. */
LIBZHIAPI int zhi_add_file(ZHIState *s, const char *filename);

/* compile a string containing a C source. Return -1 if error. */
LIBZHIAPI int zhi_compile_string(ZHIState *s, const char *buf);

/* Tip: to have more specific errors/warnings from zhi_compile_string(),
   you can prefix the string with "#line <num> \"<filename>\"\n" */

/*****************************/
/* linking commands */

/* set output type. MUST BE CALLED before any compilation */
LIBZHIAPI int zhi_set_output_type(ZHIState *s, int output_type);
#define ZHI_OUTPUT_MEMORY   1 /* output will be run in memory */
#define ZHI_OUTPUT_EXE      2 /* executable file */
#define ZHI_OUTPUT_DLL      4 /* dynamic library */
#define ZHI_OUTPUT_OBJ      3 /* object file */
#define ZHI_OUTPUT_PREPROCESS 5 /* only preprocess */

/* equivalent to -Lpath option */
LIBZHIAPI int zhi_add_library_path(ZHIState *s, const char *pathname);

/* the library name is the same as the argument of the '-l' option */
LIBZHIAPI int zhi_add_library(ZHIState *s, const char *libraryname);

/* add a symbol to the compiled program */
LIBZHIAPI int zhi_add_symbol(ZHIState *s, const char *name, const void *val);

/* output an executable, library or object file. DO NOT call
   zhi_relocate() before. */
LIBZHIAPI int zhi_output_file(ZHIState *s, const char *filename);

/* link and run main() function and return its value. DO NOT call
   zhi_relocate() before. */
LIBZHIAPI int zhi_run(ZHIState *s, int argc, char **argv);

/* do all relocations (needed before using 取符号值()) */
LIBZHIAPI int zhi_relocate(ZHIState *s1);

/* return symbol value or NULL if not found */
LIBZHIAPI void *取符号值(ZHIState *s, const char *name);

/* list all (global) symbols and their values via 'symbol_cb()' */
LIBZHIAPI void zhi_list_symbols(ZHIState *s, void *ctx,void (*symbol_cb)(void *ctx, const char *name, const void *val));


#ifdef __cplusplus
}
#endif

#endif
